#include <condition_variable>
#include <functional>
#include <thread>
#include <vector>
#include <iostream>

class EventLoop
{
public:
    using callable_t = std::function<void()>;
    EventLoop() = default;
    ~EventLoop() noexcept
    {
        enqueue([this]
            {
                m_running = false;
            });
        std::cout << "step.02: other thread print.\n";
        m_thread.join();
    }
    //禁用移动构造 & 拷贝构造
    EventLoop(const EventLoop&) = delete;
    EventLoop(const EventLoop&&) = delete;
    EventLoop& operator= (const EventLoop&) = delete;
    EventLoop& operator= (const EventLoop&&)  = delete;
    void enqueue(callable_t&& callable) noexcept
    {
        {
            std::lock_guard<std::mutex> guard(m_mutex);
            m_writeBuffer.emplace_back(std::move(callable));
        }
        m_condVar.notify_one();
    }
private:
    std::vector<callable_t> m_writeBuffer;
    std::mutex m_mutex;
    std::condition_variable m_condVar;
    bool m_running{ true };
    std::thread m_thread{ &EventLoop::threadFunc, this};
    void threadFunc() noexcept
    {
        std::vector<callable_t> readBuffer;
        while (m_running)
        {
            {
                std::unique_lock<std::mutex> lock(m_mutex);
                m_condVar.wait(lock, [this]
                    {
                        return !m_writeBuffer.empty();
                    });
                std::swap(readBuffer, m_writeBuffer);
            }
            for (callable_t& func : readBuffer)
            {
                func();
            }
            readBuffer.clear();
        }
        std::cout << "step.03: event loop end.\n";
    }
};

int main()
{
    EventLoop eventLoop;
    eventLoop.enqueue([]
    {
        std::cout << "Event_01 is running.\n";
    });
    eventLoop.enqueue([]
    {
        std::cout << "Event_02 is running.\n";
     });
    eventLoop.enqueue([]
    {
        std::cout << "Event_03 is running.\n";
    });
    std::cout << "step.01: main thread print.\n";
}